#include "widget.h"
#include "ui_widget.h"

int dataLen;
int transmitObj = -1;//0为串口，1为tcp

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    QStringList serialNamePort;
    ui->setupUi(this);
    this->setWindowTitle("絆V0.0.1");
    /* 创建一个串口对象 */
    serialPort = new QSerialPort(this);
    /* 搜索所有可用串口 */
    foreach (const QSerialPortInfo &inf0, QSerialPortInfo::availablePorts()) {
        serialNamePort<<inf0.portName();
    }
    ui->COMComboBox->addItems(serialNamePort);
    QObject::connect(serialPort, &QSerialPort::readyRead, this, &Widget::on_readyRead);
    //显示默认图像
    img = new QImage;
    img->load("://image/kizuna&friends.jpg");
    ui->imgLabel->setPixmap(QPixmap::fromImage(img->scaled(ui->imgLabel->width(),ui->imgLabel->height(),
                                                                   Qt::KeepAspectRatio, Qt::FastTransformation)));
    imgGrey = new QImage(ui->imgWidth->currentText().toInt(), ui->imgHeight->currentText().toInt(),QImage::Format_Grayscale8);
    //创建tcp和套接字对象
    tcpServer = new QTcpServer;
    tcpSocket = new QTcpSocket;
    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(new_client()));
    //关联数据信号
//    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(read_data()));
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_openButton_clicked()
{
    transmitObj = 0;
    /* 串口设置 */
    serialPort->setPortName(ui->COMComboBox->currentText());
    serialPort->setBaudRate(ui->baudrateComboBox->currentText().toInt());
    serialPort->setDataBits((QSerialPort::DataBits)(ui->comDataBits->currentText().toInt()));
    switch (ui->comStopBits->currentIndex()) {
    case 0:
        serialPort->setStopBits(QSerialPort::OneStop);
        break;
    case 1:
        serialPort->setStopBits(QSerialPort::OneAndHalfStop);
        break;
    case 2:
        serialPort->setStopBits(QSerialPort::TwoStop);
        break;
    default:
        serialPort->setStopBits(QSerialPort::OneStop);
        break;
    }
    switch (ui->comParity->currentIndex()) {
    case 0:
        serialPort->setParity(QSerialPort::EvenParity);
        break;
    case 1:
        serialPort->setParity(QSerialPort::MarkParity);
        break;
    case 2:
        serialPort->setParity(QSerialPort::NoParity);
        break;
    case 3:
        serialPort->setParity(QSerialPort::OddParity);
        break;
    case 4:
        serialPort->setParity(QSerialPort::SpaceParity);
        break;
    default:
        serialPort->setParity(QSerialPort::NoParity);
        break;
    }

    /* 打开串口提示框 */
    if (true == serialPort->open(QIODevice::ReadWrite))
    {
        QMessageBox::information(this, "提示", "串口打开成功");
        ui->COMComboBox->setEnabled(false);
        ui->baudrateComboBox->setEnabled(false);
        ui->comDataBits->setEnabled(false);
        ui->comStopBits->setEnabled(false);
        ui->comParity->setEnabled(false);
        ui->tab_2->setEnabled(false);
    }
    else
    {
        QMessageBox::critical(this, "提示", "串口打开失败, id:" + QString::number(serialPort->error()));
    }
}


void Widget::on_closeButton_clicked()
{
    serialPort->close();
    ui->COMComboBox->setEnabled(true);
    ui->baudrateComboBox->setEnabled(true);
    ui->comDataBits->setEnabled(true);
    ui->comStopBits->setEnabled(true);
    ui->comParity->setEnabled(true);
    ui->tab_2->setEnabled(true);
}

void Widget::on_sendButton_clicked()//发送事件
{
    static qint64 sendcount = 0;
    QByteArray data = ui->sendText->toPlainText().toUtf8();
    //发送计数
    sendcount += data.size();
    ui->sendCNT->setText(QString::number(sendcount));

    switch (transmitObj) {
    case 0:
        serialPort->write(data);
        break;
    case 1:
        tcpSocket->write(data);
        break;
    default:
        break;
    }

}


void Widget::on_clearReceive_clicked()//清空接收区
{
    ui->receiveText->clear();
}

void Widget::on_readyRead()//接收事件
{
    static qint64 mesc = QDateTime::currentMSecsSinceEpoch();
    static unsigned char tmp;
    static int cnt = 0;
    static int byteCnt = 0;
    static bool imgFlag = false;
    static unsigned char *uch = &tmp;
    static int headpacket = 0;
    static qint64 recvcount = 0;
    static double fps = 0;
    QIODevice *objPtr;

    switch (transmitObj) {//选择传输设备
    case 0:
        objPtr = serialPort;
        break;
    case 1:
        objPtr = tcpSocket;
        break;
    default:
        return;
    }

    //从接收缓冲区中读取数据

    if(ui->checkProtocol->isChecked() == false)//无协议传输
    {
        QByteArray buffer = objPtr->readAll();
        QString text = ui->receiveText->toPlainText();
        if(ui->comEncode->currentIndex() == HEX)
        {
            text += ' ';
            text += buffer.toHex(' ');//string转hex，以空格填充间隔
        }else text += QString(SetCodeType(buffer, ui->comEncode->currentIndex()));
        ui->receiveText->setPlainText(text);
        recvcount += buffer.size();
        ui->recvCNT->setText(QString::number(recvcount));
    }else{//开启协议传输

        switch (ui->comProtocol->currentIndex()) {
        case 0://灰度图

            while(objPtr->read((char*)uch, 1))//一直读取直到没有可读
            {
                if(imgFlag)
                {
                    cnt++;
                    if(cnt == dataLen)//传输完毕,由于内存对齐，不能直接使用sizeInBytes（）
                    {
                        cnt = 0;
                        imgFlag = false;
                        uch = &tmp;
                        ui->imgLabel->clear();
                        ui->imgLabel->setPixmap(QPixmap::fromImage(
                                                    (imgGrey->scaled(ui->imgLabel->width(),ui->imgLabel->height(),
                                                                      Qt::KeepAspectRatio, Qt::FastTransformation))));
                        if(ui->checkSave->isChecked() == true)//保存图片
                        {
                            fileName = "";
                            fileName += saveFileName + "/Img_" + QString::number(QDateTime::currentMSecsSinceEpoch()) + ".jpg";//加上毫秒级时间戳（十三位）
                            imgGrey->save(fileName, "JPG");
                        }
                        //计算帧率
                        fps = (double)1000.0 / (QDateTime::currentMSecsSinceEpoch() - mesc);
                        mesc = QDateTime::currentMSecsSinceEpoch();
                        ui->fpsLabel->setText(QString::number(fps)+"fps");
                        break;
                    }else
                    {
                        if(cnt % imgGrey->width() == 0 && cnt != 0)
                        {
                            uch = imgGrey->scanLine(cnt / imgGrey->width());//避免内存对齐影响，行末换行
                        }else
                        {
                            uch++;//传输地址自增
                        }
                    }

                }else if((*uch == 'A') && headpacket == 0)//检验包头
                {
                    headpacket++;

                }else if((*uch == 'I') && headpacket == 1)
                {
                    imgFlag = true;//检测到包头，开始协议传输
                    uch = imgGrey->bits();//将图像地址传给接收字符
                    headpacket = 0;//包头计数清零
                }

            }
            break;
        case 1://压缩二值图
            while(objPtr->read((char*)&tmp, 1))//一直读取直到没有可读
            {
                if(imgFlag)
                {
                    for(int j = 0; j < 8; j++)
                    {
                        *uch = 255 * ((tmp >> j)& 1);//数据从低位到高位存放
                        cnt++;//cnt计数像素数量
                        if(cnt == dataLen)
                        {
                            break;
                        }else if(cnt % imgGrey->width() == 0 && cnt != 0)
                        {
                            uch = imgGrey->scanLine(cnt / imgGrey->width());//避免内存对齐影响，行末换行
                        }else
                        {
                            uch++;//传输地址自增
                        }
                    }
                    byteCnt++;
                    if(byteCnt == (dataLen / 8 + (bool)(dataLen % 8)))//不足8的倍数则补齐
                    {
                        cnt = 0;
                        byteCnt = 0;
                        imgFlag = false;
                        ui->imgLabel->clear();
                        ui->imgLabel->setPixmap(QPixmap::fromImage(
                                                    (imgGrey->scaled(ui->imgLabel->width(),ui->imgLabel->height(),
                                                                     Qt::KeepAspectRatio, Qt::FastTransformation))));
                        if(ui->checkSave->isChecked() == true)//保存图片
                        {
                            fileName = "";
                            fileName += saveFileName + "/Img_" + QString::number(QDateTime::currentMSecsSinceEpoch()) + ".jpg";//加上毫秒级时间戳（十三位）
                            imgGrey->save(fileName, "JPG");
                        }
                        //计算帧率
                        fps = (double)1000.0 / (QDateTime::currentMSecsSinceEpoch() - mesc) ;
                        mesc = QDateTime::currentMSecsSinceEpoch();
                        ui->fpsLabel->setText(QString::number(fps));
                        break;
                    }

                }else if((*uch == 'A') && headpacket == 0)//检验包头
                {
                    headpacket++;

                }else if((*uch == 'I') && headpacket == 1)
                {
                    imgFlag = true;//检测到包头，开始协议传输
                    uch = imgGrey->bits();//将图像地址传给接收字符
                    headpacket = 0;//包头计数清零
                }
            }
            break;
        default:
            break;
        }
    }
}


void Widget::on_checkProtocol_stateChanged(int arg1)
{
    if(arg1)
    {
        ui->comProtocol->setEnabled(false);//关闭传输协议选择
        ui->imgWidth->setEnabled(false);//关闭图片大小选择
        ui->imgHeight->setEnabled(false);
        imgGrey = new QImage(ui->imgWidth->currentText().toInt(), ui->imgHeight->currentText().toInt(),QImage::Format_Grayscale8);
        dataLen = imgGrey->width() * imgGrey->height();
        //*imgGrey = imgGrey->scaled(ui->imgWidth->currentText().toInt(), ui->imgHeight->currentText().toInt());
    }else
    {
        ui->comProtocol->setEnabled(true);
        ui->imgWidth->setEnabled(true);
        ui->imgHeight->setEnabled(true);
        delete imgGrey;
    }
}


void Widget::on_TcpOnButton_clicked()
{
    transmitObj = 1;
    quint16 port = ui->portNumber->text().toInt();
    switch (ui->tcpProtocol->currentIndex()) {
    case 0://Tcp Server
        tcpServer->listen(QHostAddress::Any, port);
        QMessageBox::information(this, "提示", "已启动监听");
        break;
    case 1://Tcp Cilent
        //检测链接成功信号关联槽函数
        connect(tcpSocket,SIGNAL(connected()),this,SLOT(connect_suc()));
        //检测掉线信号
        connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(client_dis()));
        //连接服务器，设置ip和端口号
        tcpSocket->connectToHost(ui->IPNumber->text(),ui->portNumber->text().toInt());
        //关联readyRead信号
        connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(on_readyRead()));
        break;
    default:
        break;
    }
    ui->tab->setEnabled(false);
    ui->tcpProtocol->setEnabled(false);
    ui->IPNumber->setEnabled(false);
    ui->portNumber->setEnabled(false);
}


void Widget::on_tcpoffButton_clicked()
{
    switch (ui->tcpProtocol->currentIndex()) {
    case 0:
        tcpServer->close();
        QMessageBox::information(this, "提示", "已停止监听");
        break;
    case 1:
        tcpSocket->disconnect();
        QMessageBox::information(this, "提示", "已断开连接");
        break;
    default:
        break;
    }
    ui->tab->setEnabled(true);
    ui->tcpProtocol->setEnabled(true);
    ui->IPNumber->setEnabled(true);
    ui->portNumber->setEnabled(true);
}


void Widget::new_client()
{
    tcpSocket = tcpServer->nextPendingConnection();//与客户端通信的socket
    //关联接收客户端数据信号readyRead信号（客户端有数据就会发readyRead信号）
//    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(read_client_data()));
    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(on_readyRead()));
    //检测掉线信号
    connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(server_dis()));
}
/*
void Widget::read_client_data()
{
    static unsigned char tmp;
    static int cnt = 0;
    static bool imgFlag = false;
    static unsigned char *uch = &tmp;
    static int headpacket = 0;
    static int byteCnt = 0;

    //可以实现同时读取多个客户端发送过来的消息
    QTcpSocket *obj = (QTcpSocket*)sender();
//    QString msg = obj->readAll();
//    ui->receiveText->setPlainText(msg);
    //qDebug()<<msg;
    if(ui->checkProtocol->isChecked() == false)//无协议传输
    {
        QByteArray buffer = obj->readAll();
        QString text = ui->receiveText->toPlainText();
        if(ui->comEncode->currentIndex() == HEX)//转码
        {
            text += ' ';
            text += buffer.toHex(' ');
        }else text += QString(GetCodeType(buffer, ui->comEncode->currentIndex()));
        ui->receiveText->setPlainText(text);
    }else{//开启协议传输

        switch (ui->comProtocol->currentIndex()) {
        case 0://灰度图

            while(obj->read((char*)uch, 1))//一直读取直到没有可读
            {
                if(imgFlag)
                {
                    cnt++;
                    if(cnt == dataLen)//传输完毕,由于内存对齐，不能直接使用sizeInBytes（）
                    {
                        cnt = 0;
                        imgFlag = false;
                        uch = &tmp;
                        ui->imgLabel->clear();
                        ui->imgLabel->setPixmap(QPixmap::fromImage(
                                                    (imgGrey->scaled(ui->imgLabel->width(),ui->imgLabel->height(),
                                                                     Qt::KeepAspectRatio, Qt::FastTransformation))));
//                        imgGrey->save();
                        break;
                    }else
                    {
                        if(cnt % imgGrey->width() == 0 && cnt != 0)
                        {
                            uch = imgGrey->scanLine(cnt / imgGrey->width());//避免内存对齐影响，行末换行
                        }else
                        {
                            uch++;//传输地址自增
                        }
                    }

                }else if((*uch == 'A') && headpacket == 0)//检验包头
                {
                    headpacket++;

                }else if((*uch == 'I') && headpacket == 1)
                {
                    imgFlag = true;//检测到包头，开始协议传输
                    uch = imgGrey->bits();//将图像地址传给接收字符
                    headpacket = 0;//包头计数清零
                }

            }
            break;
        case 1://压缩二值图
            while(obj->read((char*)&tmp, 1))//一直读取直到没有可读
            {
                if(imgFlag)
                {
                    for(int j = 0; j < 8; j++)
                    {
                        *uch = 255 * ((tmp >> j)& 1);//数据从低位到高位存放
                        cnt++;//cnt计数像素数量
                        if(cnt == dataLen)
                        {
                            break;
                        }else if(cnt % imgGrey->width() == 0 && cnt != 0)
                        {
                            uch = imgGrey->scanLine(cnt / imgGrey->width());//避免内存对齐影响，行末换行
                        }else
                        {
                            uch++;//传输地址自增
                        }
                    }
                    byteCnt++;
                    if(byteCnt == (dataLen / 8 + (bool)(dataLen % 8)))//不足8的倍数则补齐
                    {
                        cnt = 0;
                        byteCnt = 0;
                        imgFlag = false;
                        ui->imgLabel->clear();
                        ui->imgLabel->setPixmap(QPixmap::fromImage(
                                                    (imgGrey->scaled(ui->imgLabel->width(),ui->imgLabel->height(),
                                                                     Qt::KeepAspectRatio, Qt::FastTransformation))));
                        break;
                    }

                }else if((*uch == 'A') && headpacket == 0)//检验包头
                {
                    headpacket++;

                }else if((*uch == 'I') && headpacket == 1)
                {
                    imgFlag = true;//检测到包头，开始协议传输
                    uch = imgGrey->bits();//将图像地址传给接收字符
                    headpacket = 0;//包头计数清零
                }
            }
            break;
        default:
            break;
        }
    }
}
*/

void Widget::server_dis()//掉线事件
{
    QTcpSocket *obj = (QTcpSocket*)sender();//掉线对象
    QMessageBox::information(this, "提示", ("IP: "+ (obj->peerAddress().toString())+" 断开连接"));
    ui->TcpOnButton->setEnabled(true);
}

void Widget::read_server_data()
{
    QString msg = tcpSocket->readAll();

    ui->receiveText->setPlainText(msg);
}

void Widget::connect_suc()
{
    QMessageBox::information(this, "提示", "连接成功");
    ui->TcpOnButton->setEnabled(false);//如果连接成功则连接按钮不能按下
}
void Widget::client_dis()
{
    QMessageBox::information(this, "提示", "连接失败");
    ui->TcpOnButton->setEnabled(true);//如果连接没有成功则连接按钮还可以按下
    ui->tab->setEnabled(true);
    ui->tcpProtocol->setEnabled(true);
    ui->IPNumber->setEnabled(true);
    ui->portNumber->setEnabled(true);
}


void Widget::on_tcpProtocol_currentIndexChanged(int index)
{
    switch (index) {
    case 0:
        ui->TcpOnButton->setText("启动监听");
        ui->tcpoffButton->setText("停止监听");
        break;
    case 1:
        ui->TcpOnButton->setText("连接");
        ui->tcpoffButton->setText("断开连接");
        break;
    default:
        break;
    }
}


void Widget::on_comProtocol_currentIndexChanged(int index)
{
    switch (index) {
    case 0:
        break;
    case 1:
        break;
    default:
        break;
    }
}


void Widget::on_refreshButton_clicked()
{
    QStringList serialNamePort;
    /* 搜索所有可用串口 */
    foreach (const QSerialPortInfo &inf0, QSerialPortInfo::availablePorts()) {
        serialNamePort<<inf0.portName();
    }
    ui->COMComboBox->clear();
    ui->COMComboBox->addItems(serialNamePort);
}


void Widget::on_savePathButton_clicked()//选择保存位置
{
    saveFileName = QFileDialog::getExistingDirectory(this,tr("选择保存位置"),"",QFileDialog::ShowDirsOnly);
}

